iT邦幫忙

2024 iThome 鐵人賽

DAY 15
0
Mobile Development

從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始系列 第 15

從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始 Day15

  • 分享至 

  • xImage
  •  

Day15 畫線

Path為SwiftUI的畫線元件,通常可以用來畫曲線圖,或者其它圖形,一個最基本的Path使用方法:

Path { path in
    path.move(to: CGPoint(x: 50, y: 300))
    path.addLine(to: CGPoint(x: 300, y: 300))
}
.stroke(.blue, style: StrokeStyle(lineWidth: 2))

path.move表示設定線的起始點,path.addLine表示設定線的終點,所以這裡就表示畫出一條線,從位置(50, 300)到(300, 300),顯示如圖:

https://ithelp.ithome.com.tw/upload/images/20240815/20162607N4YFvxowqf.jpg

加入GeometryReader來根據螢幕的寬度調整,例如:

GeometryReader { geometry in
    let startPoint: CGFloat = 50
            
    Path { path in
        path.move(to: CGPoint(x: startPoint, y: 300))
        path.addLine(to: CGPoint(x: geometry.size.width - startPoint, y: 300))
    }
    .stroke(.blue, style: StrokeStyle(lineWidth: 2))
}

這裡我將前後距離根據螢幕寬度留白50,顯示如圖:

https://ithelp.ithome.com.tw/upload/images/20240815/201626070550Op1uOd.jpg

繼續使用path.addLine畫出一個矩形出來,例如:

Path { path in
    path.move(to: CGPoint(x: startPoint, y: 300))
    path.addLine(to: CGPoint(x: geometry.size.width - startPoint, y: 300))
    path.addLine(to: CGPoint(x: geometry.size.width - startPoint, y: 500))
    path.addLine(to: CGPoint(x: startPoint, y: 500))
    path.addLine(to: CGPoint(x: startPoint, y: 300))
}
.stroke(.blue, style: StrokeStyle(lineWidth: 2))

顯示如圖:

https://ithelp.ithome.com.tw/upload/images/20240815/20162607b8iPb7Jclm.jpg

使用迴圈重複畫出虛線出來,例如:

Path { path in
    for i in 1..<4 {
        let y = CGFloat(300 + i * 50)
        path.move(to: CGPoint(x: startPoint, y: y))
        path.addLine(to: CGPoint(x: geometry.size.width - startPoint, y: y))
    }
}
.stroke(.blue, style: StrokeStyle(lineWidth: 1, dash: [2, 2]))

在這裡畫出3條虛線,每一個虛線都間隔50。

顯示如圖:

https://ithelp.ithome.com.tw/upload/images/20240815/20162607HJwRSR2hOk.jpg

接下來宣告一個陣列用來畫出折線圖的資料,例如:

let datas: [CGFloat] = [10, 20, 35, 40, 0]

然後計算出這個線圖的範圍:

let chartWidth = geometry.size.width - startPoint * 2

根據螢幕的寬度與前後兩邊留白,算出圖只能畫在這個寬度內。

接下每一個點的x軸位置,必須要能夠根據datas的陣列內容來計算出來:

let xSpace = chartWidth / CGFloat(datas.count - 1)

表示陣列有多少個點,就計算出每一個點的距離為多少。

然後用迴圈去走訪陣列datas,計算出x的位置,與y軸位置:

let max = datas.max() ?? 0
                
for i in 0..<datas.count {
    let data = datas[i]
    let x = startPoint + CGFloat(i) * xSpace
    let y = 500 - (data * 200) / max
       
    if i == 0 {
        path.move(to: CGPoint(x: x, y: y))
    }
    else {
        path.addLine(to: CGPoint(x: x, y: y))
    }
}

因為整個線圖的y軸位置為300到500之間,所以y這裡的算法會先根據陣列的值算出比例位置之後,在使用500去減掉,畫出來的位置才會由下往上。

最後顯示如圖:

https://ithelp.ithome.com.tw/upload/images/20240815/20162607THghTCae7U.jpg

最後完整程式碼:

let datas: [CGFloat] = [10, 20, 35, 40, 0]
    
var body: some View {
    GeometryReader { geometry in
        let startPoint: CGFloat = 50
            
        Path { path in
            path.move(to: CGPoint(x: startPoint, y: 300))
            path.addLine(to: CGPoint(x: geometry.size.width - startPoint, y: 300))
            path.addLine(to: CGPoint(x: geometry.size.width - startPoint, y: 500))
            path.addLine(to: CGPoint(x: startPoint, y: 500))
            path.addLine(to: CGPoint(x: startPoint, y: 300))
        }
        .stroke(.blue, style: StrokeStyle(lineWidth: 2))
            
        Path { path in
            for i in 1..<4 {
                let y = CGFloat(300 + i * 50)
                path.move(to: CGPoint(x: startPoint, y: y))
                path.addLine(to: CGPoint(x: geometry.size.width - startPoint, y: y))
            }
        }
        .stroke(.blue, style: StrokeStyle(lineWidth: 1, dash: [2, 2]))
            
            
        Path { path in
            let chartWidth = geometry.size.width - startPoint * 2
            let xSpace = chartWidth / CGFloat(datas.count - 1)
                
            let max = datas.max() ?? 0
                
            for i in 0..<datas.count {
                let data = datas[i]
                let x = startPoint + CGFloat(i) * xSpace
                let y = 500 - (data * 200) / max
       
                if i == 0 {
                    path.move(to: CGPoint(x: x, y: y))
                }
                else {
                    path.addLine(to: CGPoint(x: x, y: y))
                }
            }
        }
        .stroke(.red, style: StrokeStyle(lineWidth: 1))
    } 
}

從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始 Day15 [完]


上一篇
從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始 Day14
下一篇
從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始 Day16
系列文
從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言